Upload File
POST
/api/v1/users/me/files/uploadUploads a base64-encoded file. If caseId is provided the file is attached to that case as an attachment on a case the patient owns. If caseId is omitted the file is saved as a general user document. isPHI and isRestricted always start as false.
cv-api-key + Bearer accessToken
Production
https://api.care360-next.carevalidate.com/api/v1/users/me/files/uploadStaging
https://api-staging.care360-next.carevalidate.com/api/v1/users/me/files/uploadnote
Send the file as base64 in data. Chunked / multipart upload is not supported. No application-layer size cap is enforced — App Engine / proxy limits apply transitively.
Headers
Headers
cv-api-keystringrequiredYour unique API key for authentication.
AuthorizationstringrequiredBearer access token from /verify-otp.
Content-TypestringrequiredMust be application/json.
Request Body
Body
namestringrequiredDisplay file name. Length 1–255.
Example:
lab-result.pdfdatastringrequiredBase64-encoded file bytes. Length ≥ 1.
caseIdstringoptionalUUID of a case owned by the patient in the calling organization. If omitted the file is saved as a general user document not linked to any case.
mimeTypestringrequiredMIME type of the upload. Must be on the allowlist.
Values:application/pdfapplication/mswordtext/csvtext/plainimage/jpegimage/pngimage/svg+xmlimage/tiffimage/webp
Behavior
A failed bucket write is followed by a soft-delete of the just-created DB row, so the row will not appear in subsequent listings.
caution
The upload response does not include uploadedBy. If your client needs uploader info immediately, follow up with GET /me/files/:id/metadata.
Example Request
- cURL
- JavaScript
- Python
curl -X POST '<BASE_URL>/api/v1/users/me/files/upload' \
-H 'cv-api-key: <redacted>' \
-H 'Authorization: Bearer <accessToken>' \
-H 'Content-Type: application/json' \
-d '{
"name": "lab-result.pdf",
"caseId": "550e8400-e29b-41d4-a716-446655440111",
"mimeType": "application/pdf",
"data": "JVBERi0xLjQK..."
}'
# Without caseId (general document)
curl -X POST '<BASE_URL>/api/v1/users/me/files/upload' \
-H 'cv-api-key: <redacted>' \
-H 'Authorization: Bearer <accessToken>' \
-H 'Content-Type: application/json' \
-d '{
"name": "consent-form.pdf",
"mimeType": "application/pdf",
"data": "JVBERi0xLjQK..."
}'
const buffer = await file.arrayBuffer();
const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));
const response = await fetch(
'<BASE_URL>/api/v1/users/me/files/upload',
{
method: 'POST',
headers: {
'cv-api-key': '<redacted>',
'Authorization': 'Bearer <accessToken>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'lab-result.pdf',
caseId: '<CASE_ID>',
mimeType: 'application/pdf',
data: base64,
}),
}
);
const data = await response.json();
console.log(data);
import base64
import requests
with open('lab-result.pdf', 'rb') as f:
data = base64.b64encode(f.read()).decode('ascii')
response = requests.post(
'<BASE_URL>/api/v1/users/me/files/upload',
headers={
'cv-api-key': '<redacted>',
'Authorization': 'Bearer <accessToken>',
'Content-Type': 'application/json',
},
json={
'name': 'lab-result.pdf',
'caseId': '<CASE_ID>',
'mimeType': 'application/pdf',
'data': data,
},
)
print(response.json())
Responses
▶200SuccessReturns the upload result. Note: uploadedBy is not included.
{
"status": 200,
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"fileName": "lab-result.pdf",
"isPHI": false,
"isRestricted": false,
"caseId": "550e8400-e29b-41d4-a716-446655440111",
"createdAt": "2026-04-30T12:34:56.000Z"
}
}
▶200Success — general documentcaseId was omitted. Returns the new UserDocument. Visible in admin panel under Documents → User Documents. Not returned by GET /me/files.
{
"status": 200,
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"fileName": "consent-form.pdf",
"isPHI": false,
"isRestricted": false,
"caseId": null,
"createdAt": "2026-04-30T12:34:56.000Z"
}
}
▶400Validation errorcv-api-key missing; body fails Zod (missing field, name too long, non-UUID caseId, unsupported mimeType, empty data).
{
"status": 400,
"success": false,
"error": "Validation failed",
"code": "VALIDATION_ERROR"
}
▶401Authentication failure
{
"status": 401,
"success": false,
"error": "Invalid or expired token",
"code": "VALIDATION_ERROR"
}
▶403Case not ownedcaseId does not belong to the patient or to the calling org.
{
"status": 403,
"success": false,
"error": "You do not have access to this case",
"code": "VALIDATION_ERROR"
}
▶500Storage failureBucket write failed. The placeholder DB row was rolled back via soft-delete.
{
"status": 500,
"success": false,
"error": "Failed to upload file",
"code": "INTERNAL_ERROR"
}
Try It Out
Try itAPI Playground
▶